﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using TheJoyOfCode.SLUploader.UploadService;
using System.ServiceModel;
using System.Windows.Threading;
using System.IO;
using System.Threading;
using System.ComponentModel;

namespace TheJoyOfCode.SLUploader
{
    public class UploadFileService
    {
        private readonly UploadSoapClient _client;
        private readonly Dispatcher _dispatcher;

        public UploadFileService(Uri endpointUri, Dispatcher dispatcher)
        {
            _dispatcher = dispatcher;
            _client = new UploadSoapClient(new BasicHttpBinding(), new EndpointAddress(endpointUri.ToString()));
            _client.UploadFileCompleted += new EventHandler<UploadFileCompletedEventArgs>(_client_UploadFileCompleted);
        }
              
        public void UploadFile(FileInfo fileInfo, bool overwrite)
        {
            ManualResetEvent mre = new ManualResetEvent(false);
            Stream stream = fileInfo.OpenRead();
            byte[] fileData = new byte[stream.Length];
            stream.Read(fileData, 0, (int)stream.Length);
            CallbackState state = new CallbackState() { ResetEvent = mre };

            _dispatcher.BeginInvoke(delegate()
            {
                _client.UploadFileAsync(fileInfo.Name, overwrite, fileData, state);
            });

            mre.WaitOne();

            if (state.Args.Error != null)
            {
                throw state.Args.Error;
            }
            if (state.Args.Result == UploadStatus.FileExists)
            {
                throw new FileExistsException(string.Format(
                    "The file '{0}' already exists at the remote storage location.",
                    fileInfo.Name));
            }
        }

        void _client_UploadFileCompleted(object sender, UploadFileCompletedEventArgs e)
        {
            CallbackState state = (CallbackState)e.UserState;
            state.Args = e;
            state.ResetEvent.Set();
        }

        private class CallbackState
        {
            public UploadFileCompletedEventArgs Args { get; set; }
            public ManualResetEvent ResetEvent { get; set; }
        }
    }

    public class FileExistsException : Exception
    {
        public FileExistsException(string message)
            : base(message)
        { }
    }

}
